package com.hui.auth.config.shiro.filter;

import com.hui.auth.dto.JsonResult;
import com.hui.auth.exception.AuthError;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 单用户登录处理
 */
@SuppressWarnings({"unchecked", "static-access"})
public class KickoutSessionFilter extends AccessControlFilter {

    //踢出状态，true标示踢出
    private final static String KICKOUT_STATUS = KickoutSessionFilter.class.getCanonicalName() + "_kickout_status";

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest httpRequest = ((HttpServletRequest) request);
        String url = httpRequest.getRequestURL().toString();
        Subject subject = getSubject(request, response);
        //如果没有登录 就直接return true
        if ((!subject.isAuthenticated() && !subject.isRemembered())) {
            return true;
        }
        Session session = subject.getSession();
//        Serializable sessionId = session.getId();
        /* 判断是否已经踢出*/
        Map map = (Map) session.getAttribute(KICKOUT_STATUS);
        if (null != map && !StringUtils.isEmpty(map.get("IP"))) {//已经被踢出
            return false;
        }
        //从缓存获取用户-Session信息 <UserId,SessionId>
        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        DefaultWebSessionManager sessionManager = (DefaultWebSessionManager) securityManager.getSessionManager();
        Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();//获取当前已登录的用户session列表
//        Session currenttSession = SecurityUtils.getSubject().getSession();
        for (Session s : sessions) {
            String sessionInRedis = String.valueOf(s.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
            String sessionCurrent = String.valueOf(s.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
            if (sessionCurrent.equals(sessionInRedis) && !s.getId().equals(session.getId())) {
                Map kickout = new HashMap();
                kickout.put("IP", request.getRemoteHost());
                s.setAttribute(KICKOUT_STATUS, kickout);//在非本次session中添加“异地登录”
                sessionManager.getSessionDAO().update(s);//修改session
            }
        }
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        /*先退出*/
        Subject subject = getSubject(request, response);
        subject.logout();
        WebUtils.getSavedRequest(request);
        /*提示异地登录*/
        JsonResult jsonResult = new JsonResult();
        jsonResult.setCode(AuthError.KICK_OUT.code);
        jsonResult.setMsg(AuthError.KICK_OUT.msg);
        HttpServletRequest httpRequest = ((HttpServletRequest) request);
        HttpServletResponse httpResponse = ((HttpServletResponse) response);
        CrosUtil.crosOrgin(httpRequest, httpResponse);
        httpResponse.getWriter().write(jsonResult.toString());
        return false;
    }
}
